﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;

namespace EmissorCTE
{
    public class WS
    {

        #region Cancelamento

        public static wsCteCancelamento.CteCancelamentoSoap12Client Cancelamento(TipoUF UF, ref wsCteCancelamento.cteCabecMsg Cabecalho, 
            Int16 TipoEmissao, Int16 IdUF, string CertificadoSerialNumber, string CertificadoFileNme, string CertificadoPassword)
        {
            wsCteCancelamento.CteCancelamentoSoap12Client ws = new wsCteCancelamento.CteCancelamentoSoap12Client(BindingPadrao(), new EndpointAddress(GetURL(UF, TipoServico.Cancelamento)));
            ws.ClientCredentials.ClientCertificate.Certificate = certificado.GetCertificado(CertificadoSerialNumber, CertificadoFileNme, CertificadoPassword);
            Cabecalho.cUF = IdUF.ToString();
            Cabecalho.versaoDados = "2.00";
            return ws;
        }

        #endregion

        #region Consulta

        public static wsCteConsulta.CteConsultaSoap12Client Consulta(TipoUF UF, ref wsCteConsulta.cteCabecMsg Cabecalho, 
            Int16 TipoEmissao, Int16 IdUF, string CertificadoSerialNumber, string CertificadoFileNme, string CertificadoPassword)
        {
            wsCteConsulta.CteConsultaSoap12Client ws = new wsCteConsulta.CteConsultaSoap12Client(BindingPadrao(), new EndpointAddress(GetURL(UF, TipoServico.Consulta)));
            ws.ClientCredentials.ClientCertificate.Certificate = certificado.GetCertificado(CertificadoSerialNumber, CertificadoFileNme, CertificadoPassword);
            Cabecalho.cUF = IdUF.ToString();
            Cabecalho.versaoDados = "2.00";
            return ws;
        }

        #endregion

        #region InutilizaNFe

        public static wsCteInutilizacao.CteInutilizacaoSoap12Client Consulta(TipoUF UF, ref wsCteInutilizacao.cteCabecMsg Cabecalho,
            Int16 TipoEmissao, Int16 IdUF, string CertificadoSerialNumber, string CertificadoFileNme, string CertificadoPassword)
        {
            wsCteInutilizacao.CteInutilizacaoSoap12Client ws = new wsCteInutilizacao.CteInutilizacaoSoap12Client(BindingPadrao(), new EndpointAddress(GetURL(UF, TipoServico.Inutilizacao)));
            ws.ClientCredentials.ClientCertificate.Certificate = certificado.GetCertificado(CertificadoSerialNumber, CertificadoFileNme, CertificadoPassword);
            Cabecalho.cUF = IdUF.ToString();
            Cabecalho.versaoDados = "2.00";
            return ws;
        }

        #endregion

        #region Recepcao

        public static wsCteRecepcao.CteRecepcaoSoap12Client Consulta(TipoUF UF, ref wsCteRecepcao.cteCabecMsg Cabecalho,
            Int16 TipoEmissao, Int16 IdUF, string CertificadoSerialNumber, string CertificadoFileNme, string CertificadoPassword)
        {
            wsCteRecepcao.CteRecepcaoSoap12Client ws = new wsCteRecepcao.CteRecepcaoSoap12Client(BindingPadrao(), new EndpointAddress(GetURL(UF, TipoServico.Recepcao)));
            ws.ClientCredentials.ClientCertificate.Certificate = certificado.GetCertificado(CertificadoSerialNumber, CertificadoFileNme, CertificadoPassword);
            Cabecalho.cUF = IdUF.ToString();
            Cabecalho.versaoDados = "2.00";
            return ws;
        }

        #endregion

        #region RecepcaoEvento

        public static wsCteRecepcaoEvento.CteRecepcaoEventoSoap12Client Consulta(TipoUF UF, ref wsCteRecepcaoEvento.cteCabecMsg Cabecalho,
            Int16 TipoEmissao, Int16 IdUF, string CertificadoSerialNumber, string CertificadoFileNme, string CertificadoPassword)
        {
            wsCteRecepcaoEvento.CteRecepcaoEventoSoap12Client ws = new wsCteRecepcaoEvento.CteRecepcaoEventoSoap12Client(BindingPadrao(), new EndpointAddress(GetURL(UF, TipoServico.RecepcaoEvento)));
            ws.ClientCredentials.ClientCertificate.Certificate = certificado.GetCertificado(CertificadoSerialNumber, CertificadoFileNme, CertificadoPassword);
            Cabecalho.cUF = IdUF.ToString();
            Cabecalho.versaoDados = "2.00";
            return ws;
        }

        #endregion

        #region RetRecepcao

        public static wsCteRetRecepcao.CteRetRecepcaoSoap12Client Consulta(TipoUF UF, ref wsCteRetRecepcao.cteCabecMsg Cabecalho,
            Int16 TipoEmissao, Int16 IdUF, string CertificadoSerialNumber, string CertificadoFileNme, string CertificadoPassword)
        {
            wsCteRetRecepcao.CteRetRecepcaoSoap12Client ws = new wsCteRetRecepcao.CteRetRecepcaoSoap12Client(BindingPadrao(), new EndpointAddress(GetURL(UF, TipoServico.RetRecepcao)));
            ws.ClientCredentials.ClientCertificate.Certificate = certificado.GetCertificado(CertificadoSerialNumber, CertificadoFileNme, CertificadoPassword);
            Cabecalho.cUF = IdUF.ToString();
            Cabecalho.versaoDados = "2.00";
            return ws;
        }

        #endregion

        #region StatusServico

        public static wsCteStatusServico.CteStatusServicoSoap12Client Consulta(TipoUF UF, ref wsCteStatusServico.cteCabecMsg Cabecalho,
            Int16 TipoEmissao, Int16 IdUF, string CertificadoSerialNumber, string CertificadoFileNme, string CertificadoPassword)
        {
            wsCteStatusServico.CteStatusServicoSoap12Client ws = new wsCteStatusServico.CteStatusServicoSoap12Client(BindingPadrao(), new EndpointAddress(GetURL(UF, TipoServico.Status)));
            ws.ClientCredentials.ClientCertificate.Certificate = certificado.GetCertificado(CertificadoSerialNumber, CertificadoFileNme, CertificadoPassword);
            Cabecalho.cUF = IdUF.ToString();
            Cabecalho.versaoDados = "2.00";
            return ws;
        }

        #endregion

        #region Configurações

        #region BindingPadrao

        private static Binding BindingPadrao()
        {
            CustomBinding cBinding = new CustomBinding();
            cBinding.Elements.Add(TextMessageEncodingElement());
            cBinding.Elements.Add(HttpsTransportElement());

            TimeSpan TimeOut = new TimeSpan(0, 2, 00);

            cBinding.CloseTimeout = TimeOut;
            cBinding.OpenTimeout = TimeOut;
            cBinding.ReceiveTimeout = TimeOut;
            cBinding.SendTimeout = TimeOut;

            return cBinding;
        }

        #endregion

        #region TextMessageEncodingElement

        private static TextMessageEncodingBindingElement TextMessageEncodingElement()
        {
            TextMessageEncodingBindingElement text = new TextMessageEncodingBindingElement();
            text.MaxReadPoolSize = 256;
            text.MaxWritePoolSize = 64;
            text.MessageVersion = MessageVersion.Soap12;
            text.ReaderQuotas.MaxDepth = 92;
            text.ReaderQuotas.MaxStringContentLength = 32768;
            text.ReaderQuotas.MaxArrayLength = 65536;
            text.ReaderQuotas.MaxBytesPerRead = 16384;
            text.ReaderQuotas.MaxNameTableCharCount = 65536;
            text.WriteEncoding = new System.Text.UTF8Encoding();
            return text;
        }

        #endregion

        #region HttpsTransportElement

        private static HttpsTransportBindingElement HttpsTransportElement()
        {
            HttpsTransportBindingElement Transport = new HttpsTransportBindingElement();

            Transport.ManualAddressing = false;
            Transport.MaxBufferSize = 524288;
            Transport.MaxReceivedMessageSize = 524288;
            Transport.AllowCookies = false;
            Transport.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
            Transport.BypassProxyOnLocal = false;
            Transport.DecompressionEnabled = false;
            Transport.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
            Transport.KeepAliveEnabled = true;
            Transport.MaxBufferSize = 524288;
            Transport.TransferMode = TransferMode.Buffered;
            Transport.UnsafeConnectionNtlmAuthentication = false;
            Transport.UseDefaultWebProxy = false;
            Transport.RequireClientCertificate = true;

            return Transport;
        }

        #endregion

        #endregion

        #region TipoServico

        public enum TipoServico
        {
            Recepcao = 1,
            RetRecepcao = 2,
            Cancelamento = 3,
            Inutilizacao = 4,
            Consulta = 5,
            Status = 6,
            RecepcaoEvento = 7
        }

        #endregion

        #region GetURL

        private static string GetURL(TipoUF UF, TipoServico Servico)
        {
            switch (UF)
            {
                case TipoUF.MG:
                    switch (Servico)
                    {
                        case TipoServico.Recepcao:
                            return "https://cte.fazenda.mg.gov.br/cte/services/CteRecepcao";
                        case TipoServico.RetRecepcao:
                            return "https://cte.fazenda.mg.gov.br/cte/services/CteRetRecepcao";
                        case TipoServico.Cancelamento:
                            return "https://cte.fazenda.mg.gov.br/cte/services/CteCancelamento";
                        case TipoServico.Inutilizacao:
                            return "https://cte.fazenda.mg.gov.br/cte/services/CteInutilizacao";
                        case TipoServico.Consulta:
                            return "https://cte.fazenda.mg.gov.br/cte/services/CteConsulta";
                        case TipoServico.Status:
                            return "https://cte.fazenda.mg.gov.br/cte/services/CteStatusServico";
                        case TipoServico.RecepcaoEvento:
                            return "https://cte.fazenda.mg.gov.br/cte/services/RecepcaoEvento";
                        default:
                            throw new NotImplementedException();
                    }
                    break;
                default:
                    throw new NotImplementedException("URL da UF não foi implementada");
            }
        }
        
        #endregion

    }
}